require "LevelHelper.Helpers.LHHelpers"
require "LevelHelper.Nodes.LHPathNode"
require "LevelHelper.Nodes.LHSettings"
require "LevelHelper.Nodes.LHAnimationNode"
require "LevelHelper.Nodes.SHDocumentLoader"
require "LevelHelper.Nodes.LHFixture"

require "LevelHelper.Nodes.LHAnimationNode"
require "box2d"
--------------------------------------------------------------------------------
--forward declaration of local functions

local untitledSpritesCount = 0;

LHSprite = Core.class(Sprite)
function LHSprite:spriteWithDictionary(spriteInfo) --returns a display object

	texDict = spriteInfo:dictForKey("TextureProperties");	
	
	self:createAnimatedSpriteFromDictionary(spriteInfo)
	
	if(self.lhActiveAnimNode == nil) then
		
		self:createSingleSpriteFromTextureDictionary(texDict, spriteInfo);
	end
	
	
	
	self:setTextureProperties(texDict);	
	
	--LevelHelper sprite properties assigned to a Corona sprite
	----------------------------------------------------------------------------
	
	if(spriteInfo:objectForKey("SHSceneName"))then	
		self.shSceneName = spriteInfo:stringForKey("SHSceneName")
	end
	
	if(spriteInfo:objectForKey("SHSheetName"))then	
		self.shSheetName = spriteInfo:stringForKey("SHSheetName");
	end
	if(spriteInfo:objectForKey("SHSpriteName"))then
		self.shSpriteName= spriteInfo:stringForKey("SHSpriteName");	
	end
	
	if(spriteInfo:objectForKey("UniqueName"))then
		self.lhUniqueName = spriteInfo:stringForKey("UniqueName");		
	else
		self.lhUniqueName = "UntitledSprite_" .. tostring(untitledSpritesCount);
		untitledSpritesCount = untitledSpritesCount + 1;
	end
	
	self.lhZOrder = texDict:intForKey("ZOrder");
	self.lhTag = texDict:intForKey("Tag");
	self.lhAttachedJoint = {}
	self.lhFixtures = nil
	self.lhNodeType = "LHSprite"
	
	self:addEventListener(Event.ENTER_FRAME, self.enterFrame, self)
	
	self:createPhysicObject(spriteInfo);
	
	self:setUserClassProperties(spriteInfo);
	
	self:loadPathMovementFromDictionary(spriteInfo);
	
	if self.lhActiveAnimNode then
		self:prepareAnimationNamed(self:animationName());
		if( self.lhActiveAnimNode.lhAnimAtStart)then
			self.lhActiveAnimNode:addEnterFrameEvent();
			self:playAnimation();
		end
	end

    self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self);
    self:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self);
    self:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self);
    self:addEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self);
    
end

function LHSprite:uniqueName()
	return self.lhUniqueName;
end

function LHSprite:tag()
	return self.lhTag;
end

function LHSprite:userCustomInfoClassName()
	return self.lhClassName   
end

function LHSprite:userCustomInfo()
	 return self.lhUserCustomInfo;
end

function LHSprite:onTouchesBegin(event)
    if(self:hitTestPoint(event.touch.x, event.touch.y))then
        if(self.lhTouchesBeginEvent ~= nil)then
            event.object = self;
            self.lhTouchesBeginEvent(event); 
        end
        if(self.lhSwallowTouchesBegin ~= nil and self.lhSwallowTouchesBegin == true)then
            event:stopPropagation()
        end
    end
end

function LHSprite:onTouchesMove(event)
    if(self:hitTestPoint(event.touch.x, event.touch.y))then
        if(self.lhTouchesMoveEvent ~= nil)then
            event.object = self;
            self.lhTouchesMoveEvent(event); 
        end
        if(self.lhSwallowTouchesMove ~= nil and self.lhSwallowTouchesMove == true)then
            event:stopPropagation()
        end
    end
end

function LHSprite:onTouchesEnd(event)
    if(self:hitTestPoint(event.touch.x, event.touch.y))then
        if(self.lhTouchesEndEvent ~= nil)then
            event.object = self;
            self.lhTouchesEndEvent(event); 
        end
        if(self.lhSwallowTouchesEnd ~= nil and self.lhSwallowTouchesEnd == true)then
            event:stopPropagation()
        end
    end
end

function LHSprite:onTouchesCancel(event)
    if(self:hitTestPoint(event.touch.x, event.touch.y))then
        if(self.lhTouchesCancelEvent ~= nil)then
            event.object = self;
            self.lhTouchesCancelEvent(event); 
        end
        if(self.lhSwallowTouchesCancel ~= nil and self.lhSwallowTouchesCancel == true)then
            event:stopPropagation()
        end
    end
end

function LHSprite:enterFrame(event)

	if(self.body)then
		self:setPosition(self.body:getPosition())
		self:setRotation(self.body:getAngle() * 180 / math.pi)
	end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function LHSprite:removeSelf()
	--print("calling LHSprite removeSelf " .. self.lhUniqueName .. " parent " .. self:getParent().lhUniqueName);
	--remove all properties of this sprite here
	
    self:removeEventListener(Event.ENTER_FRAME, self.enterFrame, self); 
   
    self:removeEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self);
    self:removeEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self);
    self:removeEventListener(Event.TOUCHES_END, self.onTouchesEnd, self);
    self:removeEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self);
    
    
   if(self.lhAnimationNodes)then --maybe the sprite does not have animations
		for i=1, #self.lhAnimationNodes do
			local node = self.lhAnimationNodes[i];
			if(node ~= nil)then
				node:removeSelf();
			end
			node = nil
			self.lhAnimationNodes[i] = nil
		end
	end
	self.lhAnimationNodes = nil;


	self:stopPathMovement()
	self:removeAllAttachedJoints()
		
	self.lhScaleHeight = nil
	self.lhScaleWidth = nil;
	self.lhUniqueName = nil;
	self.shSceneName = nil;
	self.shSheetName = nil;
	self.lhNodeType = nil;
	self.shSpriteName = nil;

	if(self.b2World)then
		if(self.body)then
			self.b2World:destroyBody(self.body);
		end
	end
	if(self.lhFixtures)then --it may be that sprite has no physics 
		for i = 1, #self.lhFixtures do
			self.lhFixtures[i]:removeSelf()
			self.lhFixtures[i] = nil;
		end
		self.lhFixtures = nil;
	end
	
		
	self.b2World = nil;
	self:removeFromParent();
end

    
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--Tranformation methods
function LHSprite:transformPosition(posx, posy)
	
	if(self.body)then
		self.body:setPosition(posx, posy);
	end
	self:setPosition(posx,posy);
end
--------------------------------------------------------------------------------
function LHSprite:transformRotation(rot)
	if(self.body)then
		self.body:setAngle(0.01745329252*rot);
	end
	self:setRotation(rot);
end
--------------------------------------------------------------------------------
function LHSprite:transformScaleX(newScaleX)
	self.xScale = newScaleX;
	self:recreatePhysicObject(self.lhPhysicalInfo);
end
function LHSprite:transformScaleY(newScaleY)
	self.yScale = newScaleY;
	self:recreatePhysicObject(self.lhPhysicalInfo);
end
function LHSprite:transformScale(newScale)
	self.xScale = newScale;
	self.yScale = newScale;
	self:recreatePhysicObject(self.lhPhysicalInfo);
end


--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--ANIMATION METHODS
function LHSprite:prepareAnimationNamed(animName) --this overloads setSequence()

	if(self.lhActiveAnimNode ~= nil)then
		self.lhActiveAnimNode:removeEnterFrameEvent()
	end
	
	self.lhActiveAnimNode = nil;
	if(self.lhAnimationNodes)then
		for i=1, #self.lhAnimationNodes do
			local node = self.lhAnimationNodes[i];
			if(node.lhUniqueName == animName)then
				self.lhActiveAnimNode = self.lhAnimationNodes[i];
				self.lhActiveAnimNode.paused = true;
				self.lhActiveAnimNode:addEnterFrameEvent();
				return;
			end
		end
	end
end
--------------------------------------------------------------------------------
function LHSprite:playAnimation() --this overloads play()
	if(self.lhActiveAnimNode)then
		self.lhActiveAnimNode:prepare()
		self.lhActiveAnimNode.paused = false;
	end
end
--------------------------------------------------------------------------------
function LHSprite:pauseAnimation() --this overloads pause()
	if(self.lhActiveAnimNode)then
		--self:pause();
		self.lhActiveAnimNode.paused = true;
	end
end
--------------------------------------------------------------------------------
function LHSprite:currentAnimationFrame() --this overloads currentFrame()
	if(self.lhActiveAnimNode)then
		return self.lhActiveAnimNode.currentFrame;
	end
	return -1;
end
--------------------------------------------------------------------------------
function LHSprite:restartAnimation()
	self:setAnimationFrame(1);
	self:playAnimation();
end
--------------------------------------------------------------------------------
function LHSprite:isAnimationPaused()
	if(self.lhActiveAnimNode)then
		return self.lhActiveAnimNode.paused;
	end
	return true;
end
--------------------------------------------------------------------------------
function LHSprite:animationName()
	if(self.lhActiveAnimNode)then
		return self.lhActiveAnimNode.lhUniqueName;
	end
	return ""
end
--------------------------------------------------------------------------------
function LHSprite:numberOfFrames()
	if(self.lhActiveAnimNode)then
		return #self.lhActiveAnimNode.lhFrames;
	end
	return 0;
end
--------------------------------------------------------------------------------
function LHSprite:setAnimationFrame(frmNo)
	
	if(self.lhActiveAnimNode)then
		self.lhActiveAnimNode:setCurrentFrame(frmNo);
	end
end
--------------------------------------------------------------------------------
function LHSprite:setNextFrame()
	self:setAnimationFrame(self:currentAnimationFrame()+1)
end
--------------------------------------------------------------------------------
function LHSprite:setPreviousFrame()
	self:setAnimationFrame(self:currentAnimationFrame()-1)
end
--------------------------------------------------------------------------------
function LHSprite:setNextFrameAndLoop()
	
	if(self.lhActiveAnimNode)then
		local nextFrm = self:currentAnimationFrame()+1;
		
		if(nextFrm > self:numberOfFrames())then
			nextFrm = 1;
		end
		self:setAnimationFrame(nextFrm);
	end
end
--------------------------------------------------------------------------------
function LHSprite:setPreviousFrameAndLoop()

	if(self.lhActiveAnimNode)then
		local prevFrm = self:currentAnimationFrame()-1;
		
		if(prevFrm <= 0)then
			prevFrm = self:numberOfFrames();
		end
		self:setAnimationFrame(prevFrm);
	end
end
--------------------------------------------------------------------------------
function LHSprite:isAnimationAtLastFrame()
	if(self:numberOfFrames() == self:currentAnimationFrame())then
		return true;
	end
	return false;
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--PATH METHODS
--for notifications please consult the api documentation or LHPathNode.lua
--------------------------------------------------------------------------------
function LHSprite:prepareMovementOnPathWithUniqueName(pathName)

	if(pathName == nil)then
		print("Invalid argument in prepareMovementOnPathWithUniqueName");
		return
	end
				
	local allLayers = LHSettings:sharedInstance().allLHMainLayers
		
	local bezier = nil;
	for i = 1, #allLayers do
		local layer = allLayers[i];
		if(layer)then
			bezier = layer:bezierWithUniqueName(pathName);
			if(bezier)then
				break;
			end
		end
	end
	
	if(bezier)then
	
		self.lhPathNode = LHPathNode.new();
		self.lhPathNode:initWithPoints(bezier.lhPathPoints, self);
		local path = self.lhPathNode;
		
		self.lhPathUniqueName = pathName;
		path.flipX			 = self.pathDefaultFlipX;
		path.flipY			 = self.pathDefaultFlipY;
		path.isCyclic		= self.pathDefaultIsCyclic;
		path:setMoveUsingDelta(self.pathDefaultRelativeMove);
		path.axisOrientation= self.pathDefaultOrientation;
		path.restartOtherEnd= self.pathDefaultRestartOtherEnd;
		path:setSpeed(self.pathDefaultSpeed)
		path:setStartAtEndPoint(self.pathDefaultStartPoint);
		self:pausePathMovement()
	  else
		  print("UniqueName " .. pathName .. " for path is not valid. Path movement is ignored on sprite " .. selfSprite.lhUniqueName);
	  end
end
--------------------------------------------------------------------------------
function LHSprite:pathUniqueName()
	if(self.lhPathNode)then
		return self.lhPathUniqueName;
	end
	return ""
end
--------------------------------------------------------------------------------
function LHSprite:startPathMovement()
	if(self.lhPathNode)then
		self.lhPathNode.paused = false;
	end
end
--------------------------------------------------------------------------------
function LHSprite:pausePathMovement()
	if(self.lhPathNode)then
		self.lhPathNode.paused = true;
	end
end
--------------------------------------------------------------------------------
function LHSprite:isPathMovementPaused()
	if(self.lhPathNode)then
		return self.lhPathNode.paused;
	end
	return true;
end
--------------------------------------------------------------------------------
function LHSprite:restartPathMovement()
	if(self.lhPathNode)then
		self.lhPathNode:restart();
	end
end
--------------------------------------------------------------------------------
function LHSprite:stopPathMovement() --removes the path movement;
	if(self.lhPathNode)then
		self.lhPathNode.paused = true;
		self.lhPathNode:removeSelf();
		self.lhPathNode = nil
	end
end
--------------------------------------------------------------------------------
function LHSprite:setPathMovementSpeed(value)
	if(self.lhPathNode)then
		self.lhPathNode:setSpeed(value);
	end
end
--------------------------------------------------------------------------------
function LHSprite:pathMovementSpeed()
	if(self.lhPathNode)then
		return self.lhPathNode.speed;
	end
	return 0;
end
--------------------------------------------------------------------------------
function LHSprite:setPathMovementStartPoint(point) --0 first point 1 last point
	if(point ~= 0 and point ~= 1)then
		print("Valid start path movement points are 0 and 1");
		return
	end
	if(self.lhPathNode)then
		self.lhPathNode:setStartAtEndPoint(point);
	end
end
--------------------------------------------------------------------------------
function LHSprite:pathMovementStartPoint()
	if(self.lhPathNode)then
		return self.lhPathNode.startAtEndPoint;
	end
	return -1;
end
--------------------------------------------------------------------------------
function LHSprite:setPathMovementIsCyclic(isCyclic)
	if(self.lhPathNode)then
		self.lhPathNode.isCyclic = isCyclic;
	end
end
--------------------------------------------------------------------------------
function LHSprite:pathMovementIsCyclic()
	if(self.lhPathNode)then
		return self.lhPathNode.isCyclic;
	end
	return false;
end
--------------------------------------------------------------------------------
function LHSprite:setPathMovementRestartsAtOtherEnd(otherEnd)
	if(self.lhPathNode)then
		self.lhPathNode.restartOtherEnd = otherEnd;
	end
end
--------------------------------------------------------------------------------
function LHSprite:pathMovementRestartsAtOtherEnd()
	if(self.lhPathNode)then
		return self.lhPathNode.restartOtherEnd
	end
	return false;
end
--------------------------------------------------------------------------------
function LHSprite:setPathMovementOrientation(point) --0 no orientation 1 - x 2 - y

	if(point ~= 0 or point ~= 1 or point ~= 2)then
		print("ERROR: Path movement orientation can only be 0 - no orientation 1 - x orientation, 2 - y orientation")
		return
	end

	if(self.lhPathNode)then
		self.lhPathNode.axisOrientation= point;
	end
end
--------------------------------------------------------------------------------
function LHSprite:pathMovementOrientation()
	if(self.lhPathNode)then
		return self.lhPathNode.axisOrientation;
	end
	return -1;
end
--------------------------------------------------------------------------------
function LHSprite:setPathMovementFlipXAtEnd(shouldFlipX)
	if(self.lhPathNode)then
		self.lhPathNode.flipX = shouldFlipX;
	end
end
--------------------------------------------------------------------------------
function LHSprite:pathMovementFlipXAtEnd()
	if(self.lhPathNode)then
		return self.lhPathNode.flipX;
	end
	return false;
end
--------------------------------------------------------------------------------
function LHSprite:setPathMovementFlipYAtEnd(shouldFlipY)
	if(self.lhPathNode)then
		self.lhPathNode.flipY = shouldFlipX;
	end
end
--------------------------------------------------------------------------------
function LHSprite:pathMovementFlipYAtEnd()
	if(self.lhPathNode)then
		return self.lhPathNode.flipY;
	end
end
--------------------------------------------------------------------------------
function LHSprite:setPathMovementRelative(rel)
	if(self.lhPathNode)then
		self.lhPathNode:setMoveUsingDelta(rel);
	end
end
--------------------------------------------------------------------------------
function LHSprite:pathMovementRelative()
	if(self.lhPathNode)then
		return self.lhPathNode.moveWithDelta;
	end
	return false;
end
--------------------------------------------------------------------------------
function LHSprite:pathMovementCurrentPoint()
	if(self.lhPathNode)then
		return self.lhPathNode.currentPoint;
	end
	return -1;
end
--JOINTS METHODS
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--returns the LHJoint objects attached to the sprite
function LHSprite:jointsList(selfSprite) --table contains LHJoint objects
	return selfSprite.lhAttachedJoint;
end 
--------------------------------------------------------------------------------
function LHSprite:jointWithUniqueName(selfSprite, jointName)
	for i = 1, #selfSprite.lhAttachedJoint do
		local jt = selfSprite.lhAttachedJoint[i];
		if(jt)then
			if(jt.lhUniqueName == jointName)then
				return jt;
			end
		end
	end
	return nil;
end
--------------------------------------------------------------------------------
--remove all joints attached to this sprite
function LHSprite:removeAllAttachedJoints()
	for i = 1, #self.lhAttachedJoint do
		local jt = self.lhAttachedJoint[i];
		if(jt)then
			self:removeJoint(jt);
			jt = nil
		end
	end
end
--------------------------------------------------------------------------------
function LHSprite:removeJoint(lhJointObject)

	if(lhJointObject == nil)then
		return
	end

	local foundJointObjectAttachedToSprite = false;
	
	for i = 1, #self.lhAttachedJoint do
		local jt = self.lhAttachedJoint[i];
		if(jt)then
			if(jt == lhJointObject)then
				foundJointObjectAttachedToSprite = true;
			end
		end
	end

	if(false == foundJointObjectAttachedToSprite)then
		print("ERROR: Trying to remove joint " .. lhJointObject.lhUniqueName .. " from sprite " .. self.lhUniqueName .. " but this joint is not attached to this sprite.");
		return
	end

	lhJointObject:removeSelf();
	lhJointObject = nil;
end
--------------------------------------------------------------------------------
--PRIVATE METHODS - USER SHOULD NOT CARE ABOUT THIS METHODS
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function LHSprite:createSingleSpriteFromTextureDictionary(texDict, spriteInfo)

	local spr_uvRect = texDict:rectForKey("Frame");
	
	local spriteName = spriteInfo:stringForKey("SHSpriteName");
	local sheetName = spriteInfo:stringForKey("SHSheetName");
	local sceneName = spriteInfo:stringForKey("SHSceneName");


	local shTexDict = texDict;
	if(nil == spriteInfo:objectForKey("IsSHSprite"))then--we may be loading directly from a sh dictionary
	
		local shDict = SHDocumentLoader:sharedInstance():dictionaryForSpriteNamed(spriteName,
																				  sheetName,
																				  sceneName)
		
		if(shDict)then
			   shTexDict = shDict:dictForKey("TextureProperties");
			   
			   spr_uvRect = shTexDict:rectForKey("Frame");
		end
	end
	
	local imageFile = imageFileWithFolder(spriteInfo:stringForKey("SheetImage"));	
		
	local texture = Texture.new(imageFile)
	local region = TextureRegion.new(texture, spr_uvRect.origin.x, spr_uvRect.origin.y, spr_uvRect.size.width, spr_uvRect.size.height);

	local bitmapSprite = Bitmap.new(region)
	bitmapSprite:setAnchorPoint(0.5, 0.5);
	self:addChild(bitmapSprite);

	return bitmapSprite;
	
end
--------------------------------------------------------------------------------
function LHSprite:createAnimatedSpriteFromDictionary(spriteInfo)

	if(spriteInfo == nil)then
		return nil
	end

	local sprAnimInfo = spriteInfo:dictForKey("AnimationsProperties");

	if(sprAnimInfo == nil)then
		return nil;
	end
	

	local animName = sprAnimInfo:objectForKey("AnimName")
	if(nil == animName)then 
		animName = sprAnimInfo:objectForKey("UniqueName") --in case we are loading from SH doc
		if(nil == animName)then
			return nil;
		end
	end
	
	local shSceneName = spriteInfo:stringForKey("SHSceneName");
	local animDict = SHDocumentLoader:sharedInstance():dictionaryForAnimationNamed(animName:stringValue(),--sprAnimInfo:stringForKey("AnimName"), 
																				   shSceneName);

	local animNode = LHAnimationNode:new()
	animNode:animationWithDictionary(animDict);
	if(animNode == nil)then
		return nil
	end
	
	--now set anim properties from the settings inside the level file
	if(sprAnimInfo:objectForKey("AnimRepetitions"))then
		animNode.lhRepetitions = sprAnimInfo:intForKey("AnimRepetitions")
	else
		animNode.lhRepetitions = sprAnimInfo:intForKey("Repetitions") --from SH
	end
	if(sprAnimInfo:objectForKey("AnimLoop"))then
		animNode.lhLoop = sprAnimInfo:boolForKey("AnimLoop")
	else
		animNode.lhLoop = sprAnimInfo:boolForKey("Loop")--from SH
	end
	
	if(sprAnimInfo:objectForKey("AnimRestoreOriginalFrame"))then
		animNode.lhRestoreOriginalFrame = sprAnimInfo:boolForKey("AnimRestoreOriginalFrame")
	else
		animNode.lhRestoreOriginalFrame = sprAnimInfo:boolForKey("RestoreOriginalFrame")
	end
	
	if(sprAnimInfo:objectForKey("AnimSpeed"))then
		animNode.lhDelayPerUnit = sprAnimInfo:floatForKey("AnimSpeed")
	else
		animNode.lhDelayPerUnit = sprAnimInfo:floatForKey("DelayPerUnit")
	end
	
	if(sprAnimInfo:objectForKey("AnimAtStart"))then
		animNode.lhAnimAtStart = sprAnimInfo:boolForKey("AnimAtStart")
	else
		animNode.lhAnimAtStart = sprAnimInfo:boolForKey("StartAtLaunch")
	end
	
	--local imageFile = imageFileWithFolder(animNode.lhSheetImage);		
	--local options = SHDocumentLoader:sharedInstance():sheetOptionsForImageNamed(animNode.lhSheetName, 
	--																			shSceneName)

	----------------------------------------------------------------------------------------
	-------------------------------------------------------------------------------------------
	-------------------------------------------------------------------------------------------
	
	local otherAnimationsInfo =	nil;
	if(sprAnimInfo:objectForKey("OtherAnimations"))then
		otherAnimationsInfo = sprAnimInfo:arrayForKey("OtherAnimations");
	end
	

	local otherOptions = {};
	
	if(otherAnimationsInfo ~= nil) then
	
	for a = 1, otherAnimationsInfo:count() do

		local otherInfo = otherAnimationsInfo:dictAtIndex(a);
	
		local otherAnimName = otherInfo:objectForKey("AnimName")
		if(nil == otherAnimName)then
			otherAnimName = otherInfo:objectForKey("UniqueName");
		end


		local otherSceneName = otherInfo:objectForKey("SHScene");
			
		if(otherAnimName ~= nil and otherSceneName ~= nil)then
	
			local otherAnimDict = SHDocumentLoader:sharedInstance():dictionaryForAnimationNamed(otherAnimName:stringValue(), 
																								otherSceneName:stringValue());

	
			local otherAnimNode = nil;
		
			if(otherAnimDict ~= nil)then
				otherAnimNode = LHAnimationNode:new();
				otherAnimNode:animationWithDictionary(otherAnimDict);
			end
			
			if(otherAnimNode ~= nil)then

				--now set anim properties from the settings inside the level file
				if(otherInfo:objectForKey("AnimRepetitions"))then
					otherAnimNode.lhRepetitions = otherInfo:intForKey("AnimRepetitions")
				else
					otherAnimNode.lhRepetitions = otherInfo:intForKey("Repetitions") --from SH
				end
				
				if(otherInfo:objectForKey("AnimLoop"))then
					otherAnimNode.lhLoop = otherInfo:boolForKey("AnimLoop")
				else
					otherAnimNode.lhLoop = otherInfo:boolForKey("Loop")--from SH
				end
					
				if(otherInfo:objectForKey("AnimRestoreOriginalFrame"))then
					otherAnimNode.lhRestoreOriginalFrame = otherInfo:boolForKey("AnimRestoreOriginalFrame")
				else
					otherAnimNode.lhRestoreOriginalFrame = otherInfo:boolForKey("RestoreOriginalFrame")
				end
					
				if(otherInfo:objectForKey("AnimSpeed"))then
					otherAnimNode.lhDelayPerUnit = otherInfo:floatForKey("AnimSpeed")
				else
					otherAnimNode.lhDelayPerUnit = otherInfo:floatForKey("DelayPerUnit")
				end
					
				if(otherInfo:objectForKey("AnimAtStart"))then
					otherAnimNode.lhAnimAtStart = otherInfo:boolForKey("AnimAtStart")
				else
					otherAnimNode.lhAnimAtStart = otherInfo:boolForKey("StartAtLaunch")
				end
				otherOptions[#otherOptions + 1] = {animNode = otherAnimNode};		
			end
												
		end
	end
	end

	----------------------------------------------------------------------------------------------
	----------------------------------------------------------------------------------------------
	----------------------------------------------------------------------------------------------
	
	local loop = 0;
	if false == animNode.lhLoop then
		loop = animNode.lhRepetitions
	end
			
	local speed = animNode:animationTime();
	if(speed < 0.001)then
		speed = 0.001
	end
	speed = speed*1000;
	
	self:addChild(animNode:spriteFrameAtIndex(1));
			
	self.lhAnimationNodes = {};
	
	for i = 1, #otherOptions do
		local otherOptions = otherOptions[i];
		local otherAnimNode = otherOptions.animNode;
		otherAnimNode.coronaSprite = self;
		self.lhAnimationNodes[#self.lhAnimationNodes + 1] = otherAnimNode;										
	end
	
	self.lhAnimationNodes[#self.lhAnimationNodes + 1] = animNode;
	self.lhActiveAnimNode = animNode;
	animNode.coronaSprite = self;
	
	return animSprite;
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function LHSprite:setTextureProperties(texDict)
	
	local scale = texDict:sizeForKey("Scale");
	local flipX = texDict:boolForKey("FlipX")
	local flipY = texDict:boolForKey("FlipY");

	self.lhScaleWidth = scale.width;
	self.lhScaleHeight= scale.height;
	
	self:setScale(self:getScaleX()*scale.width, self:getScaleY()*scale.height);
	
	if(flipX)then
		self:set("scaleX", -1.0*self:getScaleX());
		self.lhScaleWidth = -1.0*self.lhScaleWidth
	end
	
	if(flipY)then
		self:set("scaleY", -1.0*self:getScaleY());
		self.lhScaleHeight= -1.0*self.lhScaleHeight;
	end
						
	
	self:setRotation(texDict:intForKey("Angle"));
	self:setAlpha(texDict:floatForKey("Opacity"));
	self:setVisible(texDict:boolForKey("IsDrawable"));

	--self:setAnchorPoint(0.5, 0.5);

	local position = texDict:pointForKey("Position");
	self:setPosition(position.x, position.y);
	
	local color = texDict:rectForKey("Color");
	self:setColorTransform(color.origin.x, color.origin.y, color.size.width);

end
--------------------------------------------------------------------------------
function LHSprite:setUserClassProperties(spriteInfo)

	local classInfo = spriteInfo:dictForKey("CustomClassInfo");

	if(nil == classInfo)then
		return
	end
	
	self.lhClassName = classInfo:stringForKey("ClassName");
	
	if(self.lhClassName == nil)then
		return
	end
	
	require("LevelHelper.CustomClasses.LHCustomClasses");
	self.lhUserCustomInfo = lh_customClassInstanceWithName(self.lhClassName);

	if(self.lhUserCustomInfo == nil)then
		return
	end
	
	local classRep = classInfo:dictForKey("ClassRepresentation");
	
	self.lhUserCustomInfo:setPropertiesFromDictionary(classRep);
end
--------------------------------------------------------------------------------
function LHSprite:loadPathMovementFromDictionary(spriteInfo)

	local dictionary = spriteInfo:dictForKey("PathProperties");
	
	
	if(dictionary == nil or dictionary:isEmpty())then
		return;
	end

--	//at this point we may not have a LHBezier in the level 
--	//so we create the path after the level is fully loaded
--	//but we save the path properties here

	local pathName = dictionary:stringForKey("PathName");
	
	if(nil == pathName)then
		return
	end
	
	self.pathDefaultFlipX			 = dictionary:boolForKey("PathFlipX");
	self.pathDefaultFlipY			 = dictionary:boolForKey("PathFlipY");
	self.pathDefaultIsCyclic		 = dictionary:boolForKey("PathIsCyclic");
	self.pathDefaultRelativeMove	 = dictionary:boolForKey("PathMoveDelta");
	self.lhPathUniqueName			 = pathName;
	self.pathDefaultOrientation	 = dictionary:intForKey("PathOrientation");
	self.pathDefaultRestartOtherEnd = dictionary:boolForKey("PathOtherEnd");
	self.pathDefaultSpeed			 = dictionary:floatForKey("PathSpeed");
	self.pathDefaultStartAtLaunch	= dictionary:boolForKey("PathStartAtLaunch");
	self.pathDefaultStartPoint		 = dictionary:intForKey("PathStartPoint");
	
end
--------------------------------------------------------------------------------
function LHSprite:recreatePhysicObject(phyDict)

--first remove the previously created body - if any
	 
	 if(self.b2World == nil)then
		 return
	 end
	 
	 
	if(self.lhFixtures~= nil)then --it may be that sprite has no physics 
		for i = 1, #self.lhFixtures do
			self.lhFixtures[i]:removeSelf()
			self.lhFixtures[i] = nil;
		end
		self.b2World:destroyBody(self.body);
		self.lhFixtures = nil;
	end


	local fixturesInfo = phyDict:arrayForKey("SH_ComplexShapes");
	
	if(nil == fixturesInfo)then
		return
	end
	
	local completeBodyFixtures = {};
	
	self.lhFixtures = {};
	
	
	local pType = phyDict:intForKey("Type");							
	if(pType == 3) then
		return
	end

	local physicType = b2.STATIC_BODY;
	if(pType == 1)then
		physicType = b2.KINEMATIC_BODY;
	elseif(pType == 2)then
		physicType = b2.DYNAMIC_BODY;
	end
	
	local world = self.b2World;
	
	if(fixturesInfo:count()> 0)then
	
		local bodyDef = {};
		
		bodyDef.type = physicType;
		bodyDef.position = {x = self:getX(), y = self:getY()};
		bodyDef.fixedRotation = phyDict:boolForKey("FixedRot");
		bodyDef.bullet = phyDict:boolForKey("IsBullet");
		bodyDef.allowSleep = phyDict:boolForKey("CanSleep");
		 		
		
		self.body = world:createBody(bodyDef);	
		self.body:setAngle(0.01745329252*self:getRotation());
		self.body.lhSprite = self;
		
	end
	
	 for i=1, fixturesInfo:count() do
	
		 local fixInfo = fixturesInfo:dictAtIndex(i);
		local previousFixSize = #completeBodyFixtures
		 local fixture = LHFixture:fixtureWithDictionary(fixInfo, self, physics, completeBodyFixtures);

		local fcollisionFilter = {	 categoryBits = fixInfo:intForKey("Category"),	
									maskBits	  = fixInfo:intForKey("Mask"), 
									groupIndex	  = fixInfo:intForKey("Group") } 

		local fdensity		 = fixInfo:floatForKey("Density");
		local ffriction	 = fixInfo:floatForKey("Friction");
		local frestitution	= fixInfo:floatForKey("Restitution");
		
		local fixSensor	 = fixInfo:boolForKey("IsSensor");
	
	
		for j = 1, #fixture.fixtureShape do
			local bFix = fixture.fixtureShape[j];
			
			local fix = self.body:createFixture{shape = bFix, 
												density = fdensity, 
												restitution = frestitution, 
												friction = ffriction, 
												filter = fcollisionFilter}
			fix:setSensor(fixSensor);
			fix.lhFixture = fixture;
--			fixture.fixtureObjects[#fixture.fixtureObjects+1] = fix;
		end

		self.lhFixtures[#self.lhFixtures +1] = fixture;		
	 end
		  
	self.body:setAngularDamping(phyDict:floatForKey("AngularDamping"));
	self.body:setAngularVelocity(phyDict:floatForKey("AngularVelocity"));
	local linearVel = phyDict:pointForKey("LinearVelocity");
	self.body:setLinearVelocity(linearVel.x, linearVel.y);
	self.body:setLinearDamping(phyDict:floatForKey("LinearDamping"));
	self.body:setGravityScale(phyDict:floatForKey("GravityScale"));
	
	

end
--------------------------------------------------------------------------------
function LHSprite:createPhysicObject(spriteInfo)

	phyDict = spriteInfo:dictForKey("PhysicProperties");

	if(phyDict:boolForKey("HandledBySH")) then
		local sprDict = SHDocumentLoader:sharedInstance():dictionaryForSpriteNamed(	self.shSpriteName, 
																					self.shSheetName, 
																					self.shSceneName);
																					
																					
		if(sprDict)then
			phyDict = sprDict:dictForKey("PhysicProperties");
		end   
	end
	
	self.b2World = LHSettings:sharedInstance().activeBox2dWorld 
	
	
	self.lhPhysicalInfo = phyDict;
	self:recreatePhysicObject(phyDict)

end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------	